#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <sys/un.h>
#include <errno.h>


#include "pb.h"
#include "pb_decode.h"
#include "pb_encode.h"
#include "somb_daemon_message.h"
#include "somb_log.h"


//static int sockfd = 0;
uint32_t somb_daemon_msg_init(void)
{
    int sockfd = socket (AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
    if (sockfd < 0) {
        SOMB_LOG_ERR("somb daemon：msg create socket failed");
        return SOMB_FAIL;
    }
    
    SOMB_LOG_INFO("somb daemon: create msg socket success");
    return SOMB_OK;
}

uint32_t somb_daemon_msg_send_to_sub_ns(int daemonsk,ST_SOMB_DAEMON_SUB_NS *pstSubNs, uint32_t msgid,void *msgdata,const pb_msgdesc_t* fileds,uint32_t field_size)
{
    uint32_t ret = SOMB_OK;

    uint8_t *buffer = malloc(SOMB_DAEMON_MSG_HEADER_SIZE+field_size);

    memset(buffer,0,SOMB_DAEMON_MSG_HEADER_SIZE+field_size);


    pb_ostream_t stream = pb_ostream_from_buffer(&(buffer[SOMB_DAEMON_MSG_HEADER_SIZE]), field_size);
    bool status = pb_encode(&stream, fileds, msgdata);
    if(!status)
    {
        SOMB_LOG_ERR("somb daemon: msgid(%d) send to sub ns(%s)-id(%d)-pid(%d) msg decode error=%s",msgid,pstSubNs->name,pstSubNs->id,pstSubNs->pid,PB_GET_ERROR(&stream));
        ret = SOMB_FAIL;
    }
    else
    {
#if 0
        struct sockaddr_un dst;
        memset (&dst, 0, sizeof (dst));

        dst.sun_family = AF_UNIX;
        sprintf(dst.sun_path,SOMB_SUB_NS_ADDR_FMT0,pstSubNs->pid);

        uint32_t len = sendto(daemonsk ,buffer,somb_daemon_msg_header_size+stream.bytes_written,0,( struct sockaddr *)&dst,sun_len(&dst));
#endif
        *(uint32_t *)buffer = msgid;
        *(uint32_t *)(buffer+4) = stream.bytes_written;
        uint32_t len = send(pstSubNs->clientfd,buffer,SOMB_DAEMON_MSG_HEADER_SIZE+stream.bytes_written,MSG_NOSIGNAL);
        if( -1 == len )
        {
            SOMB_LOG_ERR("somb daemon: msgid(%d) send to sub ns(%s)-id(%d)-pid(%d)-fd(%d) failed,%s",msgid,pstSubNs->name,pstSubNs->id,pstSubNs->pid,pstSubNs->clientfd,strerror(errno));
            ret = SOMB_FAIL;
        }
        else
        {
            SOMB_LOG_DEBUG("somb daemon: msgid(%d) send to sub ns(%s)-id(%d)-pid(%d) success,len=%d,expected len=%zu",msgid,pstSubNs->name,pstSubNs->id,pstSubNs->pid,len,SOMB_DAEMON_MSG_HEADER_SIZE+stream.bytes_written);
        }
    }

    free(buffer);

    return ret ;
}

uint32_t somb_daemon_msg_send_to_ctrl(int daemonsk, uint32_t msgid,void *msgdata,const pb_msgdesc_t* fileds,uint32_t field_size)
{
    uint32_t ret = SOMB_OK;
    uint8_t *buffer = malloc(SOMB_DAEMON_MSG_HEADER_SIZE+field_size);

    memset(buffer,0,SOMB_DAEMON_MSG_HEADER_SIZE+field_size);


    pb_ostream_t stream = pb_ostream_from_buffer(&(buffer[SOMB_DAEMON_MSG_HEADER_SIZE]), field_size);
    bool status = pb_encode(&stream, fileds, msgdata);
    if(!status)
    {
        SOMB_LOG_ERR("somb daemon: msgid(%d) send to ctrl msg decode error=%s",msgid,PB_GET_ERROR(&stream));
        ret = SOMB_FAIL;
    }
    else
    {
#if 0
        struct sockaddr_un dst;
        memset (&dst, 0, sizeof (dst));

        dst.sun_family = AF_UNIX;
        sprintf(dst.sun_path,"%s",SOMB_CTRL_ADDR);

        //uint32_t len = sendto(daemonsk ,buffer,SOMB_DAEMON_MSG_HEADER_SIZE+stream.bytes_written,0,( struct sockaddr *)&dst,SUN_LEN(&dst));
#endif
        *(uint32_t *)buffer = msgid;
        *(uint32_t *)(buffer+4) = stream.bytes_written;
        uint32_t len = send(daemonsk ,buffer,SOMB_DAEMON_MSG_HEADER_SIZE+stream.bytes_written,MSG_NOSIGNAL);
        if( -1 == len )
        {
            SOMB_LOG_ERR("somb daemon: msgid(%d) send to ctrl failed,%s",msgid,strerror(errno));
            ret = SOMB_FAIL;
        }
        else
        {
            SOMB_LOG_DEBUG("somb daemon: msgid(%d) send to ctrl success,len=%d,expected len=%zu",msgid,len,SOMB_DAEMON_MSG_HEADER_SIZE+stream.bytes_written);
        }
    }

    free(buffer);

    return ret;
}
